package hypergraph;

import java.util.ArrayList;
import java.util.HashMap;

import evolution.CodonString;

import bangor.aiia.jge.evolution.Genesis;
import bangor.aiia.jge.population.InvalidPhenotypeException;



public class RuleSet extends HashMap<Character, ArrayList<HyperGraph>>{
	CodonString codons;
	String rules;
	
	public RuleSet(){
		super();
	}
	public RuleSet(CodonString codons) throws InvalidPhenotypeException{
		super();
		this.codons = codons;

		rules = generate(ParseState.RULESET);

		//System.out.println(rules);
		parse(rules);
		//System.out.println("parsed");
		//get('A').get(0).print();
		//get('B').get(0).print();
		//get('C').get(0).print();
		
	}
	
	public void parse(String str){
		str.replaceAll("[\t ]+", "");
		String[] rules = str.split("\n");
		for(String rule : rules){
			//System.out.println("Rule" + rule);
			String[] pair = rule.split("::=");
			Character c = pair[0].charAt(0);
			ArrayList<HyperGraph> replacements = new ArrayList<HyperGraph>(); 
			replacements.add(new HyperGraph(pair[1]));
			
			String[] options = pair[1].split(":");
			for(String option : options){
				//System.out.println(option);
				replacements.add(new HyperGraph(option));
			}
			put(c, replacements);
		}
	}
	
	public void addGraph(Character c, HyperGraph g){
		if(containsKey(c))
			get(c).add(g);
		else {
			ArrayList<HyperGraph> l = new ArrayList<HyperGraph>();
			l.add(g);
			put(c, l);
		}
	}
	
	public HyperGraph getGraph(char rule, int graph){
		ArrayList<HyperGraph> list = get(rule);
		return list.get(graph % list.size());
	}
	
	public HyperGraph getGraph(Character rule, int codon){
		return get(rule).get(codon % get(rule).size());
	}
	
	enum ParseState{
		RULESET, RULE, REPLACEMENT, ELEMENTS, ELEMENT, EDGE, HYPEREDGE, NODES, NODE, LABEL
	}
	
	public String generate(ParseState state) throws InvalidPhenotypeException{
		
		String result = "";
		char[] labels = new char[]{'A', 'B', 'C', 'D'};
		switch(state){
		case RULESET:
			for(int i = 0; i < labels.length; i++){
				result += labels[i] + "::=";
				result += generate(ParseState.ELEMENTS) + "\n";
			} break;
		case RULE:
			for(int i = 0; i < codons.next() + 1; i++){
				if(i > 0) result += ":";
				result += generate(ParseState.REPLACEMENT);
				
			} break;
		case REPLACEMENT:
			result += generate(ParseState.ELEMENTS);
			//if(codons.next() % 2 == 1)
			//	result += generate(ParseState.REPLACEMENT);
			break;
			
		case ELEMENTS:
			for(int i = 0; i < codons.next() + 1; i++){
				result += generate(ParseState.ELEMENT);
			}
		case ELEMENT:
			if(codons.next() % 2 == 1)
				result += generate(ParseState.EDGE);
			else
				result += generate(ParseState.HYPEREDGE);
		case EDGE:
			result += "Z" + generate(ParseState.NODE) + generate(ParseState.NODE);
			break;
		case HYPEREDGE:
			result += generate(ParseState.LABEL);
			result += generate(ParseState.NODE) + generate(ParseState.NODE);
			for(int i = 3; i < codons.next(); i++){
				result += generate(ParseState.NODE);
			}
			break;
		case NODES:
			result += generate(ParseState.NODE);
			if(codons.next() % 2 == 0)
				result += generate(ParseState.NODE);
			else 
				result += generate(ParseState.NODE);
			break;
		case NODE:
			result += codons.next();
			break;
		case LABEL:
			result += labels[codons.next()];
			
			 
		}
		return result;
	}
	
	public static void main(String[] args){
		
		
	}
	
	
}
